﻿using System;
using System.ComponentModel;
using System.Windows.Media.Imaging;

namespace SUMO.MediaBrowser.Foundation
{
    public class TabImageSyncState
    {
        public bool CancelRequested { get; set; }
    }

    public class TabImage : INotifyPropertyChanged
    {
        private readonly Guid _imageGuid;
        private long _bytesUploaded;
        private IFileUploader _fileUploader;
        private int _percentage;
        private FileStates _state;
        private byte[] imageStreamBuffer;
        public TabImageSyncState SyncState = new TabImageSyncState();

        public TabImage()
        {
            _imageGuid = Guid.NewGuid();
            ScaleModifier = 1;
            State = FileStates.Pending;
        }

        /// <summary>
        /// Total number of bytes uploaded for this file.
        /// </summary>
        public long BytesUploaded
        {
            get { return _bytesUploaded; }
            set
            {
                if (_bytesUploaded != value)
                {
                    _bytesUploaded = value;
                    NotifyPropertyChanged("BytesUploaded");
                    Percentage = (int) ((value*100)/FileSize);
                }
            }
        }

        /// <summary>
        /// If an error occurs while uploading this file, the message is available via this property.
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// Size of the file, set when the FileStream is set.
        /// </summary>
        public long FileSize
        {
            get
            {
                if (ImageStreamBuffer == null)
                {
                    return 0;
                }

                return ImageStreamBuffer.Length;
            }
        }

        public IFileUploader FileUploader
        {
            get
            {
                if (_fileUploader == null)
                {
                    _fileUploader = new WcfFileUploader(this);
                    _fileUploader.UploadFinished += TabImageUploadFinished;
                    _fileUploader.UploadCancelled += TabImageUploadCancelled;
                    _fileUploader.UploadDataSent += TabImageUploadDataSent;
                    _fileUploader.UploadErrorOccurred += TabImageUploadErrorOccurred;
                    _fileUploader.UploadProcessingStarted += TabImageUploadProcessingStarted;
                }

                return _fileUploader;
            }
        }

        /// <summary>
        /// Guid that uniquely identifies this file.
        /// </summary>
        public Guid ImageGuid
        {
            get { return _imageGuid; }
        }

        public double ImageHeight { get; set; }

        public byte[] ImageStreamBuffer
        {
            get
            {
                if (imageStreamBuffer == null)
                {
                    //TODO: Rewire this
                    //imageStreamBuffer = Parent.Reference.ImageTypes[ParentIndex].ImageAsStreamBuffer;
                }

                return imageStreamBuffer;
            }
            set { imageStreamBuffer = value; }
        }

        public ImageTypeOption ImageType { get; set; }
        public double ImageWidth { get; set; }

        /// <summary>
        /// Returns true if this file is in one of the completed states: Finished, Cancelled, or Error.
        /// </summary>
        public bool IsCompleted
        {
            get { return _state == FileStates.Finished || _state == FileStates.Cancelled || _state == FileStates.Error; }
        }

        //public TabImageGroup Parent { get; set; }
        public int ParentIndex { get; set; }

        /// <summary>
        /// Current completion percentage.
        /// </summary>
        public int Percentage
        {
            get { return _percentage; }
            set
            {
                if (_percentage != value)
                {
                    _percentage = value;
                    NotifyPropertyChanged("Percentage");
                }
            }
        }
        
        /// <summary>
        /// Gets or sets the number of times the image is toggles between full size and scaled down. 
        /// Used to check against so that full size images can be scaled down the first time they are viewed.
        /// </summary>
        public int ResizeCounter { get; set; }
        public ImageSaveState SaveState { get; set; }
        public double ScaleModifier { get; set; }
        public ScaleTypeOption ScaleType { get; set; }

        /// <summary>
        /// Current state of the file
        /// </summary>
        public FileStates State
        {
            get { return _state; }
            set
            {
                if (_state != value)
                {
                    _state = value;
                    NotifyPropertyChanged("State");
                }
            }
        }

        //public string TabHeader
        //{
        //    get
        //    {
        //        if (ImageType == ImageTypeOption.Local)
        //        {
        //            return "Import";
        //        }

        //        ImageSize imageSize = SessionObjects.RetrieveSpecificCropSize(ImageWidth, ImageHeight);
        //        if (imageSize != null)
        //        {
        //            return imageSize.Name;
        //        }

        //        return String.Concat("Custom ", (int) ImageWidth, " x ", (int) ImageHeight);
        //    }
        //}

        /// <summary>
        /// Cancel the upload of this file.
        /// </summary>
        public void CancelUpload()
        {
            // TODO: Need to include call to WCF as part of cancelling, possibly?

            if (State == FileStates.Uploading)
            {
                lock (SyncState)
                {
                    SyncState.CancelRequested = true;
                }

                State = FileStates.Cancelling;
            }
        }

        public BitmapImage CreateImageSource()
        {
            if (ImageStreamBuffer == null)
            {
                return null;
            }

            BitmapImage imageIn = new BitmapImage();
            imageIn.SetSource(LibraryHelper.ConvertBufferToStream(ImageStreamBuffer));
            return imageIn;
        }

        /// <summary>
        /// Upload the file.
        /// </summary>
        /// <param name="uploadedFileProcessorType">type name for a class that will do post-processing on the uploaded files</param>
        public void Upload(string uploadedFileProcessorType)
        {
            // if we're already uploading, don't do anything
            if (State == FileStates.Uploading)
                return;

            State = FileStates.Uploading;
            FileUploader.StartUpload(uploadedFileProcessorType);
        }

        private void NotifyPropertyChanged(string prop)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(prop));
        }

        private void TabImageUploadCancelled(object sender, EventArgs e)
        {
            _fileUploader = null;
            State = FileStates.Cancelled;
        }

        private void TabImageUploadDataSent(object sender, UploadDataSentArgs e)
        {
            BytesUploaded = e.TotalDataSent;
        }

        private void TabImageUploadErrorOccurred(object sender, UploadErrorOccurredEventArgs e)
        {
            _fileUploader = null;
            ErrorMessage = e.ErrorMessage;
            State = FileStates.Error;
        }

        private void TabImageUploadFinished(object sender, EventArgs e)
        {
            _fileUploader = null;
            SaveState = ImageSaveState.SavedToDatabase;
            State = FileStates.Finished;
        }

        private void TabImageUploadProcessingStarted(object sender, EventArgs e)
        {
            State = FileStates.Processing;
        }

        #region Implementation of INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}